﻿using SmartHRMS.Model.Account;
using StructureMap;
using System.Text;
using System;
using SmartHRMS.Infrastructure;
using SmartHRMS.CustomExceptions.Infrastructure;
using SmartHRMS.Model;

namespace SmartHRMS.Presentation.Account
{
    public class UserPresenter 
    {
        private IPrincipalService _ICustomPrincipalService = ObjectFactory.GetInstance<IPrincipalService>();
        private IUserView view;
        private IUserService userService;
        private User user;
        private Mode mode;

        public UserPresenter(IUserView view)
        : this(ObjectFactory.GetInstance<IUserService>(), view)
        {
        }

        public UserPresenter(IUserService userService, IUserView view)
        {
            this.view = view;
            this.userService = userService;
        }

        private void setButtonText()
        {
            if (mode == Mode.Add)
            {
                view.SaveButtonText = "Save";
            }
            else
            {
                view.SaveButtonText = "Update";
            }
        }

        private void setTitleText()
        {
            if (mode == Mode.Add)
            {
                view.ViewTitle("Add");
            }
            else
            {
                view.ViewTitle("Edit");
            }
        }

        private void ClearInfoAndErrorMessages()
        {
            view.ErrorMessage(string.Empty);
            view.InfoMessage(string.Empty);
            view.WarringMessage(string.Empty);
        }

        private void DisplayErrorsIn(User user)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("There were some problems when trying to save this user information:");
            sb.Append(Environment.NewLine);
            sb.Append(Environment.NewLine);

            foreach (BrokenRule brokenRule in user.GetBrokenRules())
            {
                sb.Append(brokenRule.Rule);
                sb.Append(Environment.NewLine);
                view.ErrorMessage(sb.ToString());
            }
        }

        public void ClearView()
        {
            view.UserName = "";
            view.EmployeeCode = "";
            view.InsertedBy = "";
            view.InsertedDate = "";
            view.UpdatedBy = "";
            view.UpdatedDate = "";
            view.InsertedByName = "";
            view.UpdatedByName = "";
            view.UserAvailableMessage = "";
        }

        /// <summary>
        /// Updates the the presentation view.
        /// </summary>
        /// <param name="user">The user object.</param>
        private void UpdateView(User user)
        {
            view.UserName = user.UserName;
            view.EmployeeCode = user.EmployeeCode;
            CommonFields commonFields = new CommonFields(
                user.CommonFields.InsertedBy,
                user.CommonFields.InsertedDate,
                user.CommonFields.UpdatedBy,
                user.CommonFields.UpdatedDate);
            view.InsertedBy = commonFields.InsertedBy.ToString();
            view.InsertedDate = commonFields.InsertedDate;
            view.UpdatedBy = commonFields.UpdatedBy.ToString();
            view.UpdatedDate = commonFields.UpdatedDate;
            if (commonFields.UpdatedBy != Guid.Empty && !string.IsNullOrEmpty(commonFields.UpdatedBy.ToString()))
            {
                User userActivity = new User();
                userActivity = userService.FindBy(commonFields.InsertedBy);
                view.InsertedByName = userActivity.UserName;
                userActivity = userService.FindBy(commonFields.UpdatedBy);
                view.UpdatedByName = userActivity.UserName;
            }
            else
            {
                userService.FindBy(commonFields.InsertedBy);
                view.InsertedByName = user.UserName;
            }
        }

        /// <summary>
        /// Updates the model.
        /// </summary>
        /// <param name="user">The user object.</param>
        private void UpdateModel(User user)
        {
            user.UserName = view.UserName;
            user.EmployeeCode = view.EmployeeCode;
            user.Password = view.Password;
            user.RePassword = view.RePassword;
            if (mode == Mode.Add)
            {
                CommonFields commonFields = new CommonFields(
                    new Guid(_ICustomPrincipalService.User.UserId.ToString()), 
                    DateTime.Now.ToString(),
                    new Guid(_ICustomPrincipalService.User.UserId.ToString()),
                    DateTime.Now.ToString());

                user.CommonFields = commonFields;
            }
            else
            {
                CommonFields commonFields = new CommonFields(
                    new Guid(_ICustomPrincipalService.User.UserId.ToString()),
                    DateTime.Now.ToString());
                user.CommonFields.InsertedBy = user.CommonFields.InsertedBy;
                user.CommonFields.InsertedDate = user.CommonFields.InsertedDate;
                user.CommonFields.UpdatedBy = commonFields.UpdatedBy;
                user.CommonFields.UpdatedDate = commonFields.UpdatedDate;
            }
        }

        private User GetSelectedUserDetail()
        {
            if (user == null)
            {
                if (view.UserId == Guid.Empty)
                {
                    //Add mode
                    user = new User();
                    mode = Mode.Add;
                    user.Mode = Mode.Add; 
                }
                else
                {
                    // Edit mode
                    user = this.userService.FindBy(this.view.UserId);
                    mode = Mode.Edit;
                    user.Mode = Mode.Edit; 
                }
            }
            return user;
        }

        public void Display()
        {
            User user = GetSelectedUserDetail();

            ClearInfoAndErrorMessages();
            setButtonText();
            setTitleText();

            if (user.UserId == Guid.Empty)
            {
               // view.WarringMessage(string.Format("Could not find details from user information with Id of {0}.", view.UserId));
            }
            else
            {
                if (mode == Mode.Edit)
                    user.Mode = Mode.Edit; 
                    UpdateView(user);
            }
        }

        public void SaveUser()
        {
            User user = GetSelectedUserDetail();
            ClearInfoAndErrorMessages();
            try
            {
                UpdateModel(user);
                if (user.GetBrokenRules().Count == 0)
                {
                    try
                    {
                        user.LastPassword = Kit.EncryptPassword(user.Password);
                        this.userService.Save(user);

                        if (mode == Mode.Add)
                        {
                            this.view.InfoMessage(String.Format("User information '{0}' has been added.", user.UserName));
                            this.ClearView();
                        }
                        else
                        {
                            this.view.InfoMessage(String.Format("User information has been updated successfully."));
                        }
                    }
                    catch (Exception ex)
                    {
                        string exceptionMessage = String.Format("A problem occurred while saving company information '{0}'. {1}{2}", user.UserName, Environment.NewLine, ex.Message);
                        view.ErrorMessage(exceptionMessage);
                    }
                }
                else
                {
                    DisplayErrorsIn(user);
                }
            }
            catch (ValueObjectValidationException ex)
            {
                view.ErrorMessage(ex.Message);
            }
        }

        public bool CheckForUserNameAvailabl(string userName)
        {
            user = _ICustomPrincipalService.LoadUserByUserName(userName);
            if (user == null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
